<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <script type="application/javascript" src='https://kk-karl.github.io/booklog/js/theme-mode.js'></script>
    <link rel="stylesheet" href='https://kk-karl.github.io/booklog/css/frameworks.min.css' />
    <link rel="stylesheet" href='https://kk-karl.github.io/booklog/css/github.min.css' />
    <link rel="stylesheet" href='https://kk-karl.github.io/booklog/css/github-style.css' />
    <link rel="stylesheet" href='https://kk-karl.github.io/booklog/css/light.css' />
    <link rel="stylesheet" href='https://kk-karl.github.io/booklog/css/dark.css' />
    <link rel="stylesheet" href='https://kk-karl.github.io/booklog/css/syntax.css' />
    <title>redis限流方案汇总 - mybooklog</title>
    
    <link rel="icon" type="image/x-icon" href='../../assets/favicon.ico'>
    
    <meta name="theme-color" content="#1e2327">

    
    <meta name="description"
  content="楔子 &amp;ldquo;限流&amp;quot;这种事情即使在生活中也很常见，比如我们银行办理业务，银行不可能给去的所有人同时服务，因为柜台就那么几个。所以可能一次只给5个人办理业务，其他的人只能在后面排队；再比如打饭等等，也是一样的道理。因为能提供服务的数量有限，所以必须要通过限流的方式。
在程序的层面上也是一样的，如果我们的系统只能支持10万人同时在线购物，但是某一天突然来了100万个用户，那么后果显然是服务器直接瘫痪。因此只能让&amp;quot;限流&amp;quot;的功能来维护，先让一部分用户进行购物，其它的人进行排队，这样就等保证整个系统进行运转了。
这里提一下微博，微博因为哪个明星出轨了，或者哪个明星恋爱官宣了，导致服务器挂掉不止一次了。这里也是因为人数骤增导致的，当然这只是表层的原因，关于背后详细的架构、以及为什么这种情况一出现微博就又可能会挂掉的原因，我可能会在其它的系列中说，这里先不谈，今天主要是谈限流。
这里立一个flag，要是哪天所有人都以为还是单身的胡歌在微博上突然官宣：&amp;ldquo;大家好，这是我的妻子xxx，我们昨天领证了，希望得到大家的祝福。&amp;quot;，然后再附带两人结婚照和结婚证，我跟你说微博必瘫痪，话就撂这了。
Redis如何实现限流功能 关于限流所用的算法有两个：漏桶算法、令牌算法。
漏桶算法 漏桶算法的灵感源于漏斗，如下图所示：
首先，如果让你实现一个限流的算法你要怎么做呢？我们可以规定一个时间，比如60s，在60s之内只能处理100个请求，如果超过了100个，那么就将多余的请求丢弃掉。但是这样存在一个问题：如果在10s内请求就已经100个，因此剩余的50s只能把再来的请求给丢弃掉。但是这100个请求又花了10s中就全部处理完了，那么剩余的40s做什么？显然这样做就存在这资源浪费的情况。于是可能有人想到使用队列的方式，设置队列的容量为100，任务处理完了就出队，然后等待处理的入队，这样就保证了资源的利用率，恭喜你，漏桶算法就是这么做的。
说实话从漏斗本身上想，也能猜出使用的是队列，一边进一边出。无论漏斗上面的水流有多少，漏斗下面的水都是均匀流出的。如果上面的水流量大于下面流出的水流量的话，那么漏斗会慢慢变满；反之，漏斗永远不会被装满，并一直流出。
漏桶算法的实现步骤是：先声明一个队列保存请求，这个队列相当于漏斗，当队列容量满了之后，就放弃新来的请求。然后执行的话则是通过声明另一个线程定期从队列中获取一个或多个任务执行，这样就实现了漏桶算法。
漏桶算法可以在编程语言这一层实现。
令牌算法 令牌算法指的是有一个程序以某种恒定的速度生成令牌，并存入令牌桶中，而每个请求需要先获取令牌才能执行，如果没有获取到令牌的话则放弃执行。如下图所示：
这种令牌算法，我们也可以使用Python的threading模块来实现。
更好的限流方案 在Redis4.0，已经为我们实现了限流功能，并提供了原子的限流指令，再加上Redis这个天生的分布式程序就可以完美地实现限流了。
实现限流需要使用Redis提供的Redis-Cell模块，该模块使用的便是漏桶算法，使用起来也很简单，通过cl.throttle即可，但是我们需要提前安装。
前往：https://github.com/brandur/redis-cell/releases下载对应系统的安装包，有源码编译和安装包安装两种方式，源码编译需要rust环境、比较复杂，所以推荐安装包安装。安装之后，直接解压即可，里面会有一个libredis_cell.so文件，执行redis-cli通过module load加载即可。
&amp;gt; cl.throttle mylimit 15 30 60 1）（integer）0 # 0 表示获取成功，1 表示拒绝 2）（integer）15 # 漏斗容量 3）（integer）14 # 漏斗剩余容量 4）（integer）-1 # 被拒绝之后，多长时间之后再试（单位：秒）-1 表示无需重试 5）（integer）2 # 多久之后漏斗完全空出来 其中 15 为漏斗的容量，30 / 60s 为漏斗的速率。
通过Redis-Cell，我们则可以实现分布式原子级别的限流，更详细的使用可以查看官网" />
<meta name="keywords"
  content='blog,java,life, google analytics' />
<meta name="robots" content="noodp" />
<link rel="canonical" href="https://kk-karl.github.io/booklog/post/myblg02/" />


<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="redis限流方案汇总 - mybooklog" />
<meta name="twitter:description"
  content="楔子 &amp;ldquo;限流&amp;quot;这种事情即使在生活中也很常见，比如我们银行办理业务，银行不可能给去的所有人同时服务，因为柜台就那么几个。所以可能一次只给5个人办理业务，其他的人只能在后面排队；再比如打饭等等，也是一样的道理。因为能提供服务的数量有限，所以必须要通过限流的方式。
在程序的层面上也是一样的，如果我们的系统只能支持10万人同时在线购物，但是某一天突然来了100万个用户，那么后果显然是服务器直接瘫痪。因此只能让&amp;quot;限流&amp;quot;的功能来维护，先让一部分用户进行购物，其它的人进行排队，这样就等保证整个系统进行运转了。
这里提一下微博，微博因为哪个明星出轨了，或者哪个明星恋爱官宣了，导致服务器挂掉不止一次了。这里也是因为人数骤增导致的，当然这只是表层的原因，关于背后详细的架构、以及为什么这种情况一出现微博就又可能会挂掉的原因，我可能会在其它的系列中说，这里先不谈，今天主要是谈限流。
这里立一个flag，要是哪天所有人都以为还是单身的胡歌在微博上突然官宣：&amp;ldquo;大家好，这是我的妻子xxx，我们昨天领证了，希望得到大家的祝福。&amp;quot;，然后再附带两人结婚照和结婚证，我跟你说微博必瘫痪，话就撂这了。
Redis如何实现限流功能 关于限流所用的算法有两个：漏桶算法、令牌算法。
漏桶算法 漏桶算法的灵感源于漏斗，如下图所示：
首先，如果让你实现一个限流的算法你要怎么做呢？我们可以规定一个时间，比如60s，在60s之内只能处理100个请求，如果超过了100个，那么就将多余的请求丢弃掉。但是这样存在一个问题：如果在10s内请求就已经100个，因此剩余的50s只能把再来的请求给丢弃掉。但是这100个请求又花了10s中就全部处理完了，那么剩余的40s做什么？显然这样做就存在这资源浪费的情况。于是可能有人想到使用队列的方式，设置队列的容量为100，任务处理完了就出队，然后等待处理的入队，这样就保证了资源的利用率，恭喜你，漏桶算法就是这么做的。
说实话从漏斗本身上想，也能猜出使用的是队列，一边进一边出。无论漏斗上面的水流有多少，漏斗下面的水都是均匀流出的。如果上面的水流量大于下面流出的水流量的话，那么漏斗会慢慢变满；反之，漏斗永远不会被装满，并一直流出。
漏桶算法的实现步骤是：先声明一个队列保存请求，这个队列相当于漏斗，当队列容量满了之后，就放弃新来的请求。然后执行的话则是通过声明另一个线程定期从队列中获取一个或多个任务执行，这样就实现了漏桶算法。
漏桶算法可以在编程语言这一层实现。
令牌算法 令牌算法指的是有一个程序以某种恒定的速度生成令牌，并存入令牌桶中，而每个请求需要先获取令牌才能执行，如果没有获取到令牌的话则放弃执行。如下图所示：
这种令牌算法，我们也可以使用Python的threading模块来实现。
更好的限流方案 在Redis4.0，已经为我们实现了限流功能，并提供了原子的限流指令，再加上Redis这个天生的分布式程序就可以完美地实现限流了。
实现限流需要使用Redis提供的Redis-Cell模块，该模块使用的便是漏桶算法，使用起来也很简单，通过cl.throttle即可，但是我们需要提前安装。
前往：https://github.com/brandur/redis-cell/releases下载对应系统的安装包，有源码编译和安装包安装两种方式，源码编译需要rust环境、比较复杂，所以推荐安装包安装。安装之后，直接解压即可，里面会有一个libredis_cell.so文件，执行redis-cli通过module load加载即可。
&amp;gt; cl.throttle mylimit 15 30 60 1）（integer）0 # 0 表示获取成功，1 表示拒绝 2）（integer）15 # 漏斗容量 3）（integer）14 # 漏斗剩余容量 4）（integer）-1 # 被拒绝之后，多长时间之后再试（单位：秒）-1 表示无需重试 5）（integer）2 # 多久之后漏斗完全空出来 其中 15 为漏斗的容量，30 / 60s 为漏斗的速率。
通过Redis-Cell，我们则可以实现分布式原子级别的限流，更详细的使用可以查看官网" />
<meta name="twitter:site" content="https://kk-karl.github.io/booklog/" />
<meta name="twitter:creator" content="" />
<meta name="twitter:image"
  content="https://kk-karl.github.io/booklog/">


<meta property="og:type" content="article" />
<meta property="og:title" content="redis限流方案汇总 - mybooklog">
<meta property="og:description"
  content="楔子 &amp;ldquo;限流&amp;quot;这种事情即使在生活中也很常见，比如我们银行办理业务，银行不可能给去的所有人同时服务，因为柜台就那么几个。所以可能一次只给5个人办理业务，其他的人只能在后面排队；再比如打饭等等，也是一样的道理。因为能提供服务的数量有限，所以必须要通过限流的方式。
在程序的层面上也是一样的，如果我们的系统只能支持10万人同时在线购物，但是某一天突然来了100万个用户，那么后果显然是服务器直接瘫痪。因此只能让&amp;quot;限流&amp;quot;的功能来维护，先让一部分用户进行购物，其它的人进行排队，这样就等保证整个系统进行运转了。
这里提一下微博，微博因为哪个明星出轨了，或者哪个明星恋爱官宣了，导致服务器挂掉不止一次了。这里也是因为人数骤增导致的，当然这只是表层的原因，关于背后详细的架构、以及为什么这种情况一出现微博就又可能会挂掉的原因，我可能会在其它的系列中说，这里先不谈，今天主要是谈限流。
这里立一个flag，要是哪天所有人都以为还是单身的胡歌在微博上突然官宣：&amp;ldquo;大家好，这是我的妻子xxx，我们昨天领证了，希望得到大家的祝福。&amp;quot;，然后再附带两人结婚照和结婚证，我跟你说微博必瘫痪，话就撂这了。
Redis如何实现限流功能 关于限流所用的算法有两个：漏桶算法、令牌算法。
漏桶算法 漏桶算法的灵感源于漏斗，如下图所示：
首先，如果让你实现一个限流的算法你要怎么做呢？我们可以规定一个时间，比如60s，在60s之内只能处理100个请求，如果超过了100个，那么就将多余的请求丢弃掉。但是这样存在一个问题：如果在10s内请求就已经100个，因此剩余的50s只能把再来的请求给丢弃掉。但是这100个请求又花了10s中就全部处理完了，那么剩余的40s做什么？显然这样做就存在这资源浪费的情况。于是可能有人想到使用队列的方式，设置队列的容量为100，任务处理完了就出队，然后等待处理的入队，这样就保证了资源的利用率，恭喜你，漏桶算法就是这么做的。
说实话从漏斗本身上想，也能猜出使用的是队列，一边进一边出。无论漏斗上面的水流有多少，漏斗下面的水都是均匀流出的。如果上面的水流量大于下面流出的水流量的话，那么漏斗会慢慢变满；反之，漏斗永远不会被装满，并一直流出。
漏桶算法的实现步骤是：先声明一个队列保存请求，这个队列相当于漏斗，当队列容量满了之后，就放弃新来的请求。然后执行的话则是通过声明另一个线程定期从队列中获取一个或多个任务执行，这样就实现了漏桶算法。
漏桶算法可以在编程语言这一层实现。
令牌算法 令牌算法指的是有一个程序以某种恒定的速度生成令牌，并存入令牌桶中，而每个请求需要先获取令牌才能执行，如果没有获取到令牌的话则放弃执行。如下图所示：
这种令牌算法，我们也可以使用Python的threading模块来实现。
更好的限流方案 在Redis4.0，已经为我们实现了限流功能，并提供了原子的限流指令，再加上Redis这个天生的分布式程序就可以完美地实现限流了。
实现限流需要使用Redis提供的Redis-Cell模块，该模块使用的便是漏桶算法，使用起来也很简单，通过cl.throttle即可，但是我们需要提前安装。
前往：https://github.com/brandur/redis-cell/releases下载对应系统的安装包，有源码编译和安装包安装两种方式，源码编译需要rust环境、比较复杂，所以推荐安装包安装。安装之后，直接解压即可，里面会有一个libredis_cell.so文件，执行redis-cli通过module load加载即可。
&amp;gt; cl.throttle mylimit 15 30 60 1）（integer）0 # 0 表示获取成功，1 表示拒绝 2）（integer）15 # 漏斗容量 3）（integer）14 # 漏斗剩余容量 4）（integer）-1 # 被拒绝之后，多长时间之后再试（单位：秒）-1 表示无需重试 5）（integer）2 # 多久之后漏斗完全空出来 其中 15 为漏斗的容量，30 / 60s 为漏斗的速率。
通过Redis-Cell，我们则可以实现分布式原子级别的限流，更详细的使用可以查看官网" />
<meta property="og:url" content="https://kk-karl.github.io/booklog/post/myblg02/" />
<meta property="og:site_name" content="redis限流方案汇总" />
<meta property="og:image"
  content="https://kk-karl.github.io/booklog/">
<meta property="og:image:width" content="2048">
<meta property="og:image:height" content="1024">

<meta property="article:published_time" content="2024-04-14 13:47:36 &#43;0800 CST" />











</head>

<body>
  <div style="position: relative">
  <header class="Header js-details-container Details px-3 px-md-4 px-lg-5 flex-wrap flex-md-nowrap open Details--on">
    <div class="Header-item mobile-none" style="margin-top: -4px; margin-bottom: -4px;">
      <a class="Header-link" href="https://kk-karl.github.io/booklog/">
        <img class="octicon" height="32" width="32" src="../../images/github-mark-white.png">
      </a>
    </div>
    <div class="Header-item d-md-none">
      <button class="Header-link btn-link js-details-target" type="button"
        onclick="document.querySelector('#header-search').style.display = document.querySelector('#header-search').style.display == 'none'? 'block': 'none'">
        <img height="24" class="octicon octicon-three-bars" width="24" src="../../images/github-mark-white.png">
      </button>
    </div>
    <div style="display: none;" id="header-search"
      class="Header-item Header-item--full flex-column flex-md-row width-full flex-order-2 flex-md-order-none mr-0 mr-md-3 mt-3 mt-md-0 Details-content--hidden-not-important d-md-flex">
      <div
        class="Header-search header-search flex-auto js-site-search position-relative flex-self-stretch flex-md-self-auto mb-3 mb-md-0 mr-0 mr-md-3 scoped-search site-scoped-search js-jump-to">
        <div class="position-relative">
          <form target="_blank" action="https://www.google.com/search" accept-charset="UTF-8" method="get"
            autocomplete="off">
            <label
              class="Header-search-label form-control input-sm header-search-wrapper p-0 js-chromeless-input-container header-search-wrapper-jump-to position-relative d-flex flex-justify-between flex-items-center">
              <input type="text"
                class="Header-search-input form-control input-sm header-search-input jump-to-field js-jump-to-field js-site-search-focus js-site-search-field is-clearable"
                name="q" value="" placeholder="Search" autocomplete="off">
              <input type="hidden" name="q" value="site:https://kk-karl.github.io/booklog/">
            </label>
          </form>
        </div>
      </div>
    </div>

    <div class="Header-item Header-item--full flex-justify-center d-md-none position-relative">
      <a class="Header-link " href="https://kk-karl.github.io/booklog/">
        <img class="octicon octicon-mark-github v-align-middle" height="32" width="32" src="../../images/github-mark-white.png">
      </a>
    </div>
    <div class="Header-item" style="margin-right: 0;">
      <a href="javascript:void(0)" class="Header-link no-select" onclick="switchTheme()">
        <svg style="fill: var(--color-profile-color-modes-toggle-moon);" class="no-select" viewBox="0 0 16 16"
          version="1.1" width="16" height="16">
          <path fill-rule="evenodd" clip-rule="evenodd"
            d="M4.52208 7.71754C7.5782 7.71754 10.0557 5.24006 10.0557 2.18394C10.0557 1.93498 10.0392 1.68986 10.0074 1.44961C9.95801 1.07727 10.3495 0.771159 10.6474 0.99992C12.1153 2.12716 13.0615 3.89999 13.0615 5.89383C13.0615 9.29958 10.3006 12.0605 6.89485 12.0605C3.95334 12.0605 1.49286 10.001 0.876728 7.24527C0.794841 6.87902 1.23668 6.65289 1.55321 6.85451C2.41106 7.40095 3.4296 7.71754 4.52208 7.71754Z">
          </path>
        </svg>
      </a>
    </div>
  </header>
</div>

  
<div>
  <main>
    <div class="gisthead pagehead bg-gray-light pb-0 pt-3 mb-4">
      <div class="px-0">
        <div class="mb-3 d-flex px-3 px-md-3 px-lg-5">
          <div class="flex-auto min-width-0 width-fit mr-3">
            <div class="d-flex">
              <div class="d-none d-md-block">
                <a class="avatar mr-2 flex-shrink-0" href="https://kk-karl.github.io/booklog/">
                  <img class=" avatar-user"
                    src="../../images/avatar.png"
                    width="32" height="32"></a>
              </div>
              <div class="d-flex flex-column">
                <h1 class="break-word f3 text-normal mb-md-0 mb-1">
                  <span class="author">
                    <a href="https://kk-karl.github.io/booklog/">kk-karl</a>
                  </span>
                  <span class="path-divider">/</span>
                  <strong class="css-truncate css-truncate-target mr-1" style="max-width: 410px">
                    <a href="https://kk-karl.github.io/booklog/post/myblg02/">redis限流方案汇总</a>
                  </strong>
                </h1>
                <div class="note m-0">
                  Created <relative-time datetime="Sun, 14 Apr 2024 13:47:36 &#43;0800"
                    class="no-wrap">
                    Sun, 14 Apr 2024 13:47:36 &#43;0800</relative-time>

                  
                  <span class="file-info-divider"></span>
                  Modified <relative-time datetime="Tue, 23 Apr 2024 22:27:41 &#43;0800"
                    class="no-wrap">
                    Tue, 23 Apr 2024 22:27:41 &#43;0800</relative-time>
                  
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="container-lg px-3 new-discussion-timeline">
      <div class="repository-content gist-content">
        <div>
          <div class="js-gist-file-update-container js-task-list-container file-box">
            <div id="file-pytest" class="file my-2">
              <div id="post-header" class="file-header d-flex flex-md-items-center flex-items-start sticky-header" style="z-index: 2">
                <div class="file-info d-flex flex-md-items-center flex-items-start flex-order-1 flex-auto">
                  <div class="text-mono f6 flex-auto pr-3 flex-order-2 flex-md-order-1 mt-2 mt-md-0">
                    
                    <summary id="toc-toggle" onclick="clickToc()" class="btn btn-octicon m-0 mr-2 p-2">
                      <svg aria-hidden="true" viewBox="0 0 16 16" height="16" width="16" class="octicon octicon-list-unordered">
                        <path fill-rule="evenodd" d="M2 4a1 1 0 100-2 1 1 0 000 2zm3.75-1.5a.75.75 0 000 1.5h8.5a.75.75 0 000-1.5h-8.5zm0 5a.75.75 0 000 1.5h8.5a.75.75 0 000-1.5h-8.5zm0 5a.75.75 0 000 1.5h8.5a.75.75 0 000-1.5h-8.5zM3 8a1 1 0 11-2 0 1 1 0 012 0zm-1 6a1 1 0 100-2 1 1 0 000 2z"></path>
                      </svg>
                    </summary>
                    <details-menu class="SelectMenu" id="toc-details" style="display: none;">
                      <div class="SelectMenu-modal rounded-3 mt-1" style="max-height: 340px;">
                        <div class="SelectMenu-list SelectMenu-list--borderless p-2" style="overscroll-behavior: contain;" id="toc-list">
                        </div>
                      </div>
                    </details-menu>
                      1684 Words
                     <span class="file-info-divider"></span>
                                        1 min

                  </div>
                  <div class="file-actions flex-order-2 pt-0">
                    
                    
                    
                    <a class="muted-link mr-3" href="../../tags/%E6%8A%80%E6%9C%AF" >
                      <svg class="octicon octicon-tag" viewBox="0 0 16 16" version="1.1" width="16" height="16">
                        <path fill-rule="evenodd"
                          d="M2.5 7.775V2.75a.25.25 0 01.25-.25h5.025a.25.25 0 01.177.073l6.25 6.25a.25.25 0 010 .354l-5.025 5.025a.25.25 0 01-.354 0l-6.25-6.25a.25.25 0 01-.073-.177zm-1.5 0V2.75C1 1.784 1.784 1 2.75 1h5.025c.464 0 .91.184 1.238.513l6.25 6.25a1.75 1.75 0 010 2.474l-5.026 5.026a1.75 1.75 0 01-2.474 0l-6.25-6.25A1.75 1.75 0 011 7.775zM6 5a1 1 0 100 2 1 1 0 000-2z">
                        </path>
                      </svg>
                      技术
                    </a>
                    
                    
                    <a class="muted-link mr-3" href="../../tags/%E4%B8%AD%E9%97%B4%E4%BB%B6" >
                      <svg class="octicon octicon-tag" viewBox="0 0 16 16" version="1.1" width="16" height="16">
                        <path fill-rule="evenodd"
                          d="M2.5 7.775V2.75a.25.25 0 01.25-.25h5.025a.25.25 0 01.177.073l6.25 6.25a.25.25 0 010 .354l-5.025 5.025a.25.25 0 01-.354 0l-6.25-6.25a.25.25 0 01-.073-.177zm-1.5 0V2.75C1 1.784 1.784 1 2.75 1h5.025c.464 0 .91.184 1.238.513l6.25 6.25a1.75 1.75 0 010 2.474l-5.026 5.026a1.75 1.75 0 01-2.474 0l-6.25-6.25A1.75 1.75 0 011 7.775zM6 5a1 1 0 100 2 1 1 0 000-2z">
                        </path>
                      </svg>
                      中间件
                    </a>
                    
                    
                  </div>
                </div>
              </div>


              <div class="Box-body px-5 pb-5" style="z-index: 1">
                <article class="markdown-body entry-content container-lg"><h2 id="楔子">楔子</h2>
<p><strong>&ldquo;限流&quot;这种事情即使在生活中也很常见，比如我们银行办理业务，银行不可能给去的所有人同时服务，因为柜台就那么几个。所以可能一次只给5个人办理业务，其他的人只能在后面排队；再比如打饭等等，也是一样的道理。因为能提供服务的数量有限，所以必须要通过限流的方式。</strong></p>
<p><strong>在程序的层面上也是一样的，如果我们的系统只能支持10万人同时在线购物，但是某一天突然来了100万个用户，那么后果显然是服务器直接瘫痪。因此只能让&quot;限流&quot;的功能来维护，先让一部分用户进行购物，其它的人进行排队，这样就等保证整个系统进行运转了。</strong></p>
<blockquote>
<p><strong>这里提一下微博，微博因为哪个明星出轨了，或者哪个明星恋爱官宣了，导致服务器挂掉不止一次了。这里也是因为人数骤增导致的，当然这只是表层的原因，关于背后详细的架构、以及为什么这种情况一出现微博就又可能会挂掉的原因，我可能会在其它的系列中说，这里先不谈，今天主要是谈限流。</strong></p>
<p><strong>这里立一个flag，要是哪天所有人都以为还是单身的胡歌在微博上突然官宣：&ldquo;大家好，这是我的妻子xxx，我们昨天领证了，希望得到大家的祝福。&quot;，然后再附带两人结婚照和结婚证，我跟你说微博必瘫痪，话就撂这了。</strong></p>
</blockquote>
<h2 id="redis如何实现限流功能">Redis如何实现限流功能</h2>
<p><strong>关于限流所用的算法有两个：漏桶算法、令牌算法。</strong></p>
<h3 id="漏桶算法">漏桶算法</h3>
<p><strong>漏桶算法的灵感源于漏斗，如下图所示：</strong></p>
<p><img src="https://img2020.cnblogs.com/blog/1229382/202007/1229382-20200716164904353-1015512408.png" alt="img"></p>
<p><strong>首先，如果让你实现一个限流的算法你要怎么做呢？我们可以规定一个时间，比如60s，在60s之内只能处理100个请求，如果超过了100个，那么就将多余的请求丢弃掉。但是这样存在一个问题：如果在10s内请求就已经100个，因此剩余的50s只能把再来的请求给丢弃掉。但是这100个请求又花了10s中就全部处理完了，那么剩余的40s做什么？显然这样做就存在这资源浪费的情况。于是可能有人想到使用队列的方式，设置队列的容量为100，任务处理完了就出队，然后等待处理的入队，这样就保证了资源的利用率，恭喜你，漏桶算法就是这么做的。</strong></p>
<p><strong>说实话从漏斗本身上想，也能猜出使用的是队列，一边进一边出。无论漏斗上面的水流有多少，漏斗下面的水都是均匀流出的。如果上面的水流量大于下面流出的水流量的话，那么漏斗会慢慢变满；反之，漏斗永远不会被装满，并一直流出。</strong></p>
<p><strong>漏桶算法的实现步骤是：先声明一个队列保存请求，这个队列相当于漏斗，当队列容量满了之后，就放弃新来的请求。然后执行的话则是通过声明另一个线程定期从队列中获取一个或多个任务执行，这样就实现了漏桶算法。</strong></p>
<blockquote>
<p><strong>漏桶算法可以在编程语言这一层实现。</strong></p>
</blockquote>
<h3 id="令牌算法">令牌算法</h3>
<p><strong>令牌算法指的是有一个程序以某种恒定的速度生成令牌，并存入令牌桶中，而每个请求需要先获取令牌才能执行，如果没有获取到令牌的话则放弃执行。如下图所示：</strong></p>
<p><img src="https://img2020.cnblogs.com/blog/1229382/202007/1229382-20200716164912827-1879589360.png" alt="img"></p>
<p><strong>这种令牌算法，我们也可以使用Python的threading模块来实现。</strong></p>
<h3 id="更好的限流方案">更好的限流方案</h3>
<p><strong>在Redis4.0，已经为我们实现了限流功能，并提供了原子的限流指令，再加上Redis这个天生的分布式程序就可以完美地实现限流了。</strong></p>
<p><strong>实现限流需要使用Redis提供的Redis-Cell模块，该模块使用的便是漏桶算法，使用起来也很简单，通过cl.throttle即可，但是我们需要提前安装。</strong></p>
<p><strong>前往：<code>https://github.com/brandur/redis-cell/releases</code>下载对应系统的安装包，有源码编译和安装包安装两种方式，源码编译需要rust环境、比较复杂，所以推荐安装包安装。安装之后，直接解压即可，里面会有一个<code>libredis_cell.so</code>文件，执行redis-cli通过module load加载即可。</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">&gt; cl.throttle mylimit <span class="m">15</span> <span class="m">30</span> <span class="m">60</span>
</span></span><span class="line"><span class="cl">1）（integer）0 <span class="c1"># 0 表示获取成功，1 表示拒绝</span>
</span></span><span class="line"><span class="cl">2）（integer）15 <span class="c1"># 漏斗容量</span>
</span></span><span class="line"><span class="cl">3）（integer）14 <span class="c1"># 漏斗剩余容量</span>
</span></span><span class="line"><span class="cl">4）（integer）-1 <span class="c1"># 被拒绝之后，多长时间之后再试（单位：秒）-1 表示无需重试</span>
</span></span><span class="line"><span class="cl">5）（integer）2 <span class="c1"># 多久之后漏斗完全空出来</span>
</span></span></code></pre></div><p><strong>其中 15 为漏斗的容量，30 / 60s 为漏斗的速率。</strong></p>
<p><strong>通过Redis-Cell，我们则可以实现分布式原子级别的限流，更详细的使用可以查看官网</strong></p>
</article>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </main>
</div>
<script type="application/javascript" src='https://kk-karl.github.io/booklog/js/toc.js'></script>
<link rel="stylesheet" href='https://kk-karl.github.io/booklog/css/toc.css' />


<div id="gitalk-container" class="gitalk-container"></div>
<link rel="stylesheet" href='https://kk-karl.github.io/booklog/css/gitalk.css'>
<script src='https://kk-karl.github.io/booklog/js/gitalk.min.js'></script>
<script>
  const gitalk = new Gitalk({
    clientID: 'Your client ID',
    clientSecret: 'Your client secret',
    repo: 'kk-karl.gitee.io',
    owner: 'kk-karl',
    admin: ['kk-karl'],
    id: eval("location.pathname"), 
    distractionFreeMode: false 
  });
  (function() {
    gitalk.render('gitalk-container');
  })();
</script>


  <div class="footer container-xl width-full p-responsive">
  <div
    class="position-relative d-flex flex-row-reverse flex-lg-row flex-wrap flex-lg-nowrap flex-justify-center flex-lg-justify-between flex-sm-items-center pt-6 pb-2 mt-6 f6 text-gray border-top border-gray-light ">
    <a aria-label="Homepage" title="GitHub" class="footer-octicon d-none d-lg-block mr-lg-4" href="https://kk-karl.github.io/booklog/">
      <svg height="24" class="octicon octicon-mark-github" viewBox="0 0 16 16" version="1.1" width="24">
        <path fill-rule="evenodd"
          d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z">
        </path>
      </svg>
    </a>
    <ul class="list-style-none d-flex flex-wrap col-12 flex-justify-center flex-lg-justify-between mb-2 mb-lg-0">
      
      <li class="mr-3 mr-lg-0">© 2024-2099 mybooklog</li>
      
    </ul>
  </div>
  <div class="d-flex flex-justify-center pb-6">
    <span class="f6 text-gray-light"></span>
  </div>


</div>
</body>

<script type="application/javascript" src="https://kk-karl.github.io/booklog/js/github-style.js"></script>




</html>